//实现项目中一些公共的工具接口类

#include "logger.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <atomic>
#include <random>
#include <istream>
#include <sstream>
#include <iomanip>

namespace xchat
{
std::string uuid()
{
    //生成一个16位数字 组成的字符串作为唯一id
    //6个 0~ 255位随机数字 ->16进制 ->12个字符
    std::random_device rd; //获取随机数种子
    std::mt19937 gen(rd()); //随机数引擎
    std::uniform_int_distribution<int> dis(0, 255);
    std::stringstream ss;
    for (int i = 0; i < 6; i++)
    {
        if(i == 2) ss << "-";
        ss  << std::setw(2) << std::setfill('0') << std::hex << dis(gen);     //10 -> 0a
    }
    ss << "-";
    //2. 通过一个静态变量生成一个2字节数字 ->16进制 ->4个字符
    static std::atomic<short> idx(0);
    short tmp = idx.fetch_add(1);
    ss << std::setw(4) << std::setfill('0') << std::hex << tmp;
    return ss.str();
}
//生成四位验证码
std::string vcode()
{
    //生成一个16位数字 组成的字符串作为唯一id
    //6个 0~ 255位随机数字 ->16进制 ->12个字符
    std::random_device rd; //获取随机数种子
    std::mt19937 gen(rd()); //随机数引擎
    std::uniform_int_distribution<int> dis(0, 9);
    std::stringstream ss;
    for (int i = 0; i < 4; i++)
    {
        ss << dis(gen);
    }
    return ss.str();
}

bool readFile(const std::string &filename, std::string &body)
{
    //读取一个文件的所有数据 放入body中
    std::ifstream ifs(filename, std::ios::binary | std::ios::in);
    if (!ifs.is_open())
    {
        //打印错误原因
        LOG_ERROR("打开文件{} 失败，原因: {}", filename, strerror(errno));
        return false;
    }
    ifs.seekg(0, std::ios::end);
    size_t flen = ifs.tellg(); //获取文件大小 偏移量
    ifs.seekg(0, std::ios::beg); //跳回文件起始位置
    body.resize(flen);
    ifs.read(&body[0], flen);
    if(ifs.good() == false)
    {
        ifs.close();    
        LOG_ERROR("读取文件{} 失败，原因: {}", filename, strerror(errno));
        return false;
    }
    ifs.close();
    return true;
}
bool writeFile(const std::string &filename, const std::string &body)
{
    //将body中的数据写入到文件中
    std::ofstream ofs(filename, std::ios::binary | std::ios::out | std::ios::trunc); //trunc表示清空文件
    if (!ofs.is_open())
    {
        LOG_ERROR("打开文件{} 失败，原因: {}", filename, strerror(errno));
        return false;
    }
    ofs.write(body.c_str(), body.size());
    if(ofs.good() == false)
    {
        ofs.close();
        LOG_ERROR("写入文件{} 失败，原因: {}", filename, strerror(errno));
        return false;
    }
    ofs.close();
    return true;
}
}